#ifndef _DSWVIDEOSESSION_H
#define _DSWVIDEOSESSION_H

#include "tcpcombase.h"

#define HEADSIZE 3

#define LIVE_V_FLAG "\x00\x00\x00\x0c"
#define LIVE_V_FLAG_SIZE 4
#define LIVE_A_FLAG "\x00\x00\x00\x02"
#define LIVE_A_FLAG_SIZE 4

typedef enum{
	enmSockTypeVideo,
	enmSockTypePlay,
	enmSockTypeDown,
	enmSockTypeMax=0x0FF
} EN_SOCK_TYPE;

typedef struct
{
	unsigned char sign[4];		//0x00 00 00 0C
	unsigned int serial;
	unsigned int time;
	unsigned short width;
	unsigned short height;
	unsigned short fps;
	char	retention[10];
	char tail[4];
	unsigned int streamsize;
} __attribute__ ((packed)) TcpStreamHead_V, *LP_TcpStreamHead_V;

typedef struct{
	unsigned char sign[4];
	ST_AUDIO_FRAME_T nFrame;
} __attribute__ ((packed)) TcpStreamHead_A, *LP_TcpStreamHead_A;

typedef union
{
	TcpStreamHead_V nHead_v;
	TcpStreamHead_A nHead_a;
} __attribute__ ((packed)) Un_TcpStreamHead;

typedef struct
{
	unsigned int packsize;
	Un_TcpStreamHead head;
}TcpStreamPack, *LP_TcpStreamPack;

typedef enum{
	SESSION_UNKNOW,
	SESSION_ADD,
	SESSION_REMOVE,

	EXT_SESSION_REMOVE_RECONNECT,
	EXT_SESSION_REMOVE,
} EN_SESSION_CMD;

typedef struct{
	EN_SESSION_CMD nCmd;
	char* pKey;
	void* pParam;
} ST_SESSION_NOTIFY_T, *LPST_SESSION_NOTIFY_T;

typedef void (*CB_SESSION_NOTIFY)(LPST_SESSION_NOTIFY_T pParam, void* pCaller);

class CDswvideosession : public CTcpcombase
{
public:
	CDswvideosession();
	virtual ~CDswvideosession();
public:
	CDswvideosession(LPST_ENV_T pEnv, struct bufferevent * pBev, int nHeadSize, char* pKey, CB_SESSION_NOTIFY pNotifyFunc, void* pParent);
	static CDswvideosession* createNew(LPST_ENV_T pEnv, struct event_base *base, int nfd, int nHeadSize, char* pKey, CB_SESSION_NOTIFY pNotifyFunc, void* pParent);
private:
	virtual int MakePayloadLength(char* pData, int nLen){return ((pData[2] << 8 | pData[1]) + 1);};
	void SendMsg(char* pMsg);
	void SendVideoFrame(int nfd, LPST_VIDEO_FRAME_T pVideoFrame, int nFrameId);
	void SendAudioFrame(int nfd, LPST_AUDIO_FRAME_T pAudioFrame, int nFrameId);
	void Make_ReportID(CMarkup& xml);
	bool ProcessMessage_Ex(char* pMsg, int nLen, struct evbuffer *outbuf);
	virtual bool ProcessMessage(char* pMsg, int nLen, struct evbuffer *outbuf);
	void videoCapToSend(void* pMsg);
	void video3gpDownToSend(void* pMsg);
	void video3gpPlayToSend(void* pMsg);
	bool ReportIdResp(void* pMsgReq, const char* pMsgResp);
	bool AckReq(void* pMsgReq, const char* pMsgResp);
	void VideoSendTcpThread();
	void ExtCamVideoSendTcpThread();
	void Video3gpDownSendThread();
	void Video3gpPlaySendThread();
	bool IsAudioData(char* pData);
	bool ProcessAudioData(char* pData);
	virtual void OnError(EN_ERR_TYPE nType, struct bufferevent *bev, short events);
	void PlaybackDelay(unsigned int nInterval, int nFps, int nSpeed);

	static void cbCheckThreadFunc(int fd, short events, void* ctx){((CDswvideosession*)ctx)->CheckThreadFunc(fd, events);};
	void CheckThreadFunc(int fd, short events);

	int ConnectLocalTrans();
	bool SendToLocalTrans(int nfd, EN_D_TYPE nType, char* pData, int nLen, int &nSeq);

public:
	static bool cbReportIdResp(void* pMsgReq,const char* pMsgResp, void* pCaller){return ((CDswvideosession*)pCaller)->ReportIdResp(pMsgReq, pMsgResp);};
	static bool cbAckReq(void* pMsgReq,const char* pMsgResp, void* pCaller){return ((CDswvideosession*)pCaller)->AckReq(pMsgReq, pMsgResp);};

	static void* cbVideoSendThread(void* pvoid){((CDswvideosession*)pvoid)->VideoSendTcpThread();return NULL;};
	static void* cbExtCamVideoSendThread(void* pvoid){((CDswvideosession*)pvoid)->ExtCamVideoSendTcpThread();return NULL;};
	static void* cbVideo3gpDownSendThread(void* pvoid){((CDswvideosession*)pvoid)->Video3gpDownSendThread();return NULL;};
	static void* cbVideo3gpPlaySendThread(void* pvoid){((CDswvideosession*)pvoid)->Video3gpPlaySendThread();return NULL;}
	void SetPlaybackPos(int nPos){pthread_mutex_lock(&m_nSetAction_lock);m_nPlaybackPos = nPos;pthread_mutex_unlock(&m_nSetAction_lock);};
	void SetPlaybackSpeed(int nSpeed){pthread_mutex_lock(&m_nSetAction_lock);m_nPlayBack_Speed = nSpeed;pthread_mutex_unlock(&m_nSetAction_lock);};

	void SendTransAVData(char* pData, int nLen);
	char* GetPucId(){return m_sPucID;};
private:
	char m_sKey[64], m_sPucID[64], m_sFileName[256];

	bool m_bExtern;
	int m_chn, m_stream;
	pthread_t m_live_thread_id, m_down_thread_id, m_playback_thread_id;
	int m_nWidth, m_nHeight, m_nFps;
	bool m_bExitSendThread;
	ST_AUDIO_FRAME_T m_nAudio_Send;
	int m_audio_packetcount;
	int m_nPlayBack_Speed;
	int m_nPlaybackPos;
	pthread_mutex_t m_nSetAction_lock;

	timer_param_t m_nTaskCheckThread;

	void* m_pParent;
	CB_SESSION_NOTIFY m_pNotifyFunc;
	int m_nRecvSeq;
};

#endif

